using System;
using System.Threading;
using Microsoft.SmallBasic.Library;

namespace SmallBasicFun
{
    /// <summary>
    /// Need something to happen every hour, on the hour?
    /// Then Timer is the thing for you!
    /// Act now - time is running out!
    /// </summary>
    [SmallBasicType]
    public static class Timer
    {
        private static int interval;
        private static bool stopped;
        private static SmallBasicCallback tick;

        /// <summary>
        /// Invokes your subroutine every time the Timer ticks
        /// </summary>
        /// <example>
        /// Timer.Tick = Tock
        /// Sub Tock
        /// EndSub
        /// </example>
        public static event SmallBasicCallback Tick
        {
            add { tick += value; }

            remove { tick -= value; }
        }

        public static void Clear()
        {
            tick = null;
        }

        /// <summary>
        /// Nothin's gonna' happen, 'till you call this one
        /// </summary>
        /// <example>Timer.Start(1000)</example>
        /// <param name="intervalInMilliseconds">number of milliseconds between each Tick</param>
        public static void Start(Primitive intervalInMilliseconds)
        {
            interval = intervalInMilliseconds;
            stopped = false;
            var t = new Thread(() => Run(interval));
            RunOnce(interval);
            t.Start();
        }

        private static void Run(int intervalInMilliseconds)
        {
            while (!stopped)
            {
                RunOnce(intervalInMilliseconds);
            }
        }

        private static void RunOnce(int intervalInMilliseconds)
        {
            RunOnce(intervalInMilliseconds, tick);
        }

        public static void RunOnce(int intervalInMilliseconds, SmallBasicCallback callback)
        {
            DateTime startTime = DateTime.Now;

            if (callback != null)
            {
                callback();
            }
            DateTime endTime = DateTime.Now;
            TimeSpan time = endTime - startTime;
            if (time.TotalMilliseconds <= intervalInMilliseconds)
            {
                Thread.Sleep((int) (intervalInMilliseconds - time.TotalMilliseconds));
            }
        }
        
        /// <summary>
        /// Hammer Time! This will stop what you started
        /// </summary>
        /// <example>Timer.Stop()</example>
        public static void Stop()
        {
            stopped = true;
        }

        public static int GetInterval()
        {
            return interval;
        }
    }
}